package cn.good.yan.t3.p2;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 3. AOP  - AspectJ注解
 * @author shengren.yan
 * @create 2023-09-10
 */
@Aspect // 这个注解就是生成代理对象
@Component
@Order(1) // 设置多个类同一个方法增强，设置优先级，值越少越先执行
public class LogAdvice {

    /**
     * 切入点注解 （相同的切入点 - 提取）
     * 监听：cn.xxx的add方法进行增强
     */
    @Pointcut("execution(* cn.good.yan.t3.p2.User2.add(..))")
    private void check() {
    }

    /**
     * 前置通知  [check] 就是使用相同的切入点方法名
     */
    @Before("check()")
    public void before(JoinPoint joinPoint){
        System.out.println("before，代理逻辑前执行");
        String name = joinPoint.getSignature().getName();
        System.out.println(" 该方法名称: "+name);
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println(" 参数: "+arg);
        }

    }

    /**
     * 后置通知 - 也可以是最终通知，遇到异常也会执行
     */
//    @After("execution(* cn.good.yan.t3.p2.User2.add(..))")
    @After("check()")
    public void after(JoinPoint joinPoint){
        System.out.println("after 代理逻辑后执行");
    }

    /**
     * 前置通知 - 返回通知，有异常就不执行
     *
     * @param joinPoint
     * @param res  返回值，与 returning 里值保持一致
     */
    @AfterReturning(value = "check()", returning = "res")
    public void afterReturning(JoinPoint joinPoint, Object res) {
        System.out.println("after 代理逻辑后执行，有异常就不执行，比有@After先执行" + "返回值" + res);
    }

    /**
     * 异常通知
     *
     * @param joinPoint
     * @param ex  异常，与 Throwable 里的值保持一致
     */
    @AfterThrowing(value = "check()",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Throwable ex){
        System.out.println("after 代理逻辑后执行，有异常才执行，会执行这里" + ex.toString());
    }

    /**
     * 环绕通知
     *      期间有异常，会中断，不执行
     * @param joinPoint
     * @throws Throwable
     */
    @Around("check()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知之 前执行");
        joinPoint.proceed(); // 执行增强逻辑
        System.out.println("环绕通知之 后执行");
        return "ok";
    }

}
